#########################################################################################
# Package       Wx::Perl::SimpleThread::Handler
# Description:  Main Thread Thread Handler
# Created       Mon Mar 29 16:49:54 2010
# SVN Id        $Id: Handler.pm 5 2010-03-30 09:55:07Z mark.dootson $
# Copyright:    Copyright (c) 2010 Mark Dootson
# Licence:      This program is free software; you can redistribute it 
#               and/or modify it under the same terms as Perl itself
#########################################################################################

package Wx::Perl::SimpleThread::Handler;

#########################################################################################

use strict;
use warnings;
require Exporter;
use base qw( Exporter );
use Wx::Perl::SimpleThread;
use Time::HiRes qw( sleep );

our $VERSION = '0.02';

sub new {
    my ($class, $modulename) = @_;
    my $self =  bless {}, $class;
    my $sendq = Thread::Queue->new;
    my $recvq = Thread::Queue->new;
    my $tid = Wx::Perl::SimpleThread::_create_thread( $modulename, $sendq, $recvq );
    return undef if !$tid;
    $self->{_wxpst_sendq} = $sendq;
    $self->{_wxpst_recvq} = $recvq;
    $self->{_wxpst_tid} = $tid;
    $self->{_wxpst_thread} = threads->object($tid);
    $self->{_wxpst_terminated} = 0;
    $self->{_wxpst_busy} = 0;
    $self->{_wxpst_modulename} = $modulename; 
    return undef if !$self->{_wxpst_thread};
    Wx::Perl::SimpleThread::_add_thread_handler($self);
    return $self;
}

sub _set_busy_status { $_[0]->{_wxpst_busy} = $_[1]; }

sub _thread { $_[0]->{_wxpst_thread}; }

sub end_thread {
    my $self = shift;
    return if $self->{_wxpst_terminated};
    $self->{_wxpst_terminated} = 1;
    my $thr = $self->_thread;
    return if !$thr->is_running;
    $thr->detach if !$thr->is_detached;
    $thr->kill('TERM');
    Wx::Perl::SimpleThread::_remove_thread_handler($thr);
}

sub kill_thread {
    my $self = shift;
    return if $self->{_wxpst_terminated};
    $self->{_wxpst_terminated} = 1;
    my $thr = $self->_thread;
    return if !$thr->is_running;
    $thr->detach if !$thr->is_detached;
    $thr->kill('KILL');
    Wx::Perl::SimpleThread::_remove_thread_handler($thr);
}

sub join_thread {
    my $self = shift;
    my $timeout = shift || 5.0;
    my $killonfail = ( $timeout < 0 ) ? 1 : 0;
    $timeout = abs($timeout);
    return 1 if $self->{_wxpst_terminated};
    my $thr = $self->_thread;
    return 1 if $thr->is_detached;
    return 1 if !$thr->is_running;
    $thr->kill('TERM');
    while($timeout > 0.0) {
        if($thr->is_joinable) {
            $thr->join;
            $self->{_wxpst_terminated} = 1;
            Wx::Perl::SimpleThread::_remove_thread_handler($thr);
            last;
        } else {
            $timeout -= 0.10;
            sleep 0.10 if $timeout;
        }
    }
    $self->kill_thread if($killonfail && ($timeout <= 0.05));
    return ($timeout > 0.05) ? 1 : 0;
}

sub is_thread_running  { $_[0]->_thread->is_running; }
sub is_thread_detached { $_[0]->_thread->is_detached; }
sub is_thread_busy { return( ($_[0]->{_wxpst_busy} == 0) && ($_[0]->pending_request_count == 0)); }
sub tid { $_[0]->{_wxpst_tid}; }

sub _read_thread {
    my $self = shift;
    return undef if $self->{_wxpst_terminated};
    if(defined(my $result = $self->{_wxpst_recvq}->dequeue_nb)) {
        return $result;
    } else {
        return undef;
    }
}

sub pending_request_count { $_[0]->{_wxpst_sendq}->pending; }

sub send_thread_request { $_[0]->{_wxpst_sendq}->enqueue($_[1]); }

sub on_thread_data_event {
    my($self, $data) = @_;
}

sub on_thread_request_complete {
    my($self, $data) = @_;    
}

sub on_thread_exit_event {
    my($self) = @_;
}

sub DESTROY { $_[0]->join_thread(-5); }

1;
